# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

load("//:expand_template_with_defines.bzl", "expand_template_with_defines")
load("//:oss_java_library.bzl", "oss_java_library")
load("//:sonatype_artifact_bundle.bzl", "sonatype_artifact_bundle")
load("@com_github_johnynek_bazel_jar_jar//:jar_jar.bzl", "jar_jar")
load("@com_google_j2cl//build_defs:rules.bzl", "j2cl_application", "j2cl_import", "j2cl_library")
load("@google_bazel_common//testing:test_defs.bzl", "gen_java_tests")

package(licenses = ["notice"])

filegroup(
    name = "artifact_bundles",
    srcs = [
        ":compiler_externs_bundle",
        ":compiler_main_bundle",
        ":compiler_parent_bundle",
        ":compiler_shaded_bundle",
        ":compiler_unshaded_bundle",
    ],
)

sonatype_artifact_bundle(
    name = "compiler_shaded_bundle",
    artifact_id = "closure-compiler",
    jar = ":compiler_shaded.jar",
    javadoc = ":compiler_lib.javadoc",
    pom = "pom-main-shaded.xml",
    sources = ":compiler_lib.sources",
)

sonatype_artifact_bundle(
    name = "compiler_unshaded_bundle",
    artifact_id = "closure-compiler-unshaded",
    jar = ":compiler_unshaded_deploy.jar",
    javadoc = ":compiler_lib.javadoc",
    pom = "pom-main-unshaded.xml",
    sources = ":compiler_lib.sources",
)

sonatype_artifact_bundle(
    name = "compiler_externs_bundle",
    artifact_id = "closure-compiler-externs",
    jar = ":externs",
    pom = "externs/pom.xml",
)

sonatype_artifact_bundle(
    name = "compiler_main_bundle",
    artifact_id = "closure-compiler-main",
    pom = "pom-main.xml",
)

sonatype_artifact_bundle(
    name = "compiler_parent_bundle",
    artifact_id = "closure-compiler-parent",
    pom = "pom.xml",
)

jar_jar(
    name = "compiler_shaded",
    input_jar = ":compiler_unshaded_deploy.jar",
    rules = "rules.jarjar",
)

java_binary(
    name = "compiler_unshaded",
    main_class = "com.google.javascript.jscomp.CommandLineRunner",
    runtime_deps = [":compiler_lib"],
)

java_binary(
    name = "linter",
    main_class = "com.google.javascript.jscomp.LinterMain",
    runtime_deps = [":compiler_lib"],
)

java_library(
    name = "externs",
    resources = [":externs_zip"],
)

oss_java_library(
    name = "compiler_lib",
    java_attrs = dict(
        resources = [
            ":externs_zip",
        ] + glob([
            "src/**/*.properties",
            "src/com/google/javascript/jscomp/js/**/*.js",
            "src/com/google/javascript/jscomp/js/**/*.txt",
        ]),
    ),
    javadoc_attrs = dict(
    ),
    shared_attrs = dict(
        srcs = [
            ":CommandLineRunner_with_version",
        ] + glob(
            [
                "gen/**/*.java",
                "src/com/google/debugging/**/*.java",
                "src/com/google/javascript/jscomp/*.java",
                "src/com/google/javascript/jscomp/bundle/**/*.java",
                "src/com/google/javascript/jscomp/colors/**/*.java",
                "src/com/google/javascript/jscomp/deps/**/*.java",
                "src/com/google/javascript/jscomp/diagnostic/**/*.java",
                "src/com/google/javascript/jscomp/disambiguate/**/*.java",
                "src/com/google/javascript/jscomp/graph/**/*.java",
                "src/com/google/javascript/jscomp/ijs/**/*.java",
                "src/com/google/javascript/jscomp/resources/**/*.java",
                "src/com/google/javascript/jscomp/lint/**/*.java",
                "src/com/google/javascript/jscomp/modules/**/*.java",
                "src/com/google/javascript/jscomp/parsing/**/*.java",
                "src/com/google/javascript/jscomp/regex/**/*.java",
                "src/com/google/javascript/jscomp/transpile/**/*.java",
                "src/com/google/javascript/jscomp/type/**/*.java",
                "src/com/google/javascript/refactoring/**/*.java",
                "src/com/google/javascript/refactroing/**/*.java",
                "src/com/google/javascript/rhino/**/*.java",
            ],
            exclude = [
                "**/testing/**/*.java",
                "**/super*/**/*.java",
                "**/j2cl/**/*.java",
                "**/gwt/**/*.java",
                "src/com/google/debugging/sourcemap/*Js.java",
            ] + [
                # Used as a template.
                "src/com/google/javascript/jscomp/CommandLineRunner.java",
            ],
        ),
        deps = [
            "@args4j_args4j",
            "@com_google_code_gson_gson",
            "@com_google_guava_failureaccess//jar",
            "@com_google_guava_guava//jar",
            "@com_google_protobuf_protobuf_java",
            "@com_google_re2j_re2j",
            "@google_bazel_common//third_party/java/auto:value",
            "@google_bazel_common//third_party/java/error_prone:annotations",
            "@google_bazel_common//third_party/java/jsr305_annotations",
        ],
    ),
)

genrule(
    name = "externs_zip",
    srcs = glob(["externs/**/*.js"]),
    outs = ["externs.zip"],
    # Trim the "externs/" prefix from the names of the ziped files.
    cmd = "cd externs && find . -name '*.js' | zip ../$(OUTS) -@ &> /dev/null",
)

# It's easier to make a copy of this Java file than to update PraserConfig.properties
# because the Java compiler can tell us during build if something is wrong. By
# contrast, the ParserConfig lookup will fail at runtime.
expand_template_with_defines(
    name = "CommandLineRunner_with_version",
    out = "withversion/CommandLineRunner.java",
    defines = {
        "COMPILER_VERSION": "unspecified",
    },
    substitutions = {
        "Compiler.getReleaseVersion()": '"{COMPILER_VERSION}"',
        "Compiler.getReleaseDate()": '"unspecified"',
    },
    template = "src/com/google/javascript/jscomp/CommandLineRunner.java",
)

# To run all tests:           `blaze test //:compiler_tests`
# To test `a/b/FooTest.java`: `blaze test //:a/b/Foo`
#
# Only files ending in `*Test.java` are considered tests.
gen_java_tests(
    name = "compiler_tests",
    srcs = glob(
        [
            "test/**/*.java",
            "src/**/testing/**/*.java",
        ],
        exclude = [
            # TODO(nickreid): Reenable these when we stop running them with
            # Maven. Runfiles make them too hard to get them to pass under Maven
            # and Bazel together.
            "test/com/google/javascript/jscomp/CommandLineRunnerTest.java",
            "test/com/google/javascript/jscomp/CompilerTest.java",
            "test/com/google/javascript/jscomp/ConformanceAllowlisterTest.java",
            "test/com/google/javascript/jscomp/CoverageInstrumentationPassTest.java",
            "test/com/google/javascript/jscomp/SourceMapJsLangTest.java",
            "test/com/google/javascript/jscomp/integration/IntegrationTest.java",
            "test/com/google/javascript/refactoring/examples/*.java",
        ] + [
            # These files are only needed by the GWT/J2CL build of the compiler.
            "**/super*/**/*.java",
            "**/j2cl/**/*.java",
            "**/gwt/**/*.java",
            "src/com/google/debugging/sourcemap/*Js.java",
        ],
    ),
    prefix_path = "test/",
    deps = [
        ":compiler_lib",
        ":compiler_tests_resources",
        "@args4j_args4j",
        "@com_google_code_gson_gson",
        "@com_google_guava_failureaccess//jar",
        "@com_google_guava_guava//jar",
        "@com_google_guava_guava_testlib//jar",
        "@com_google_protobuf_protobuf_java",
        "@com_google_re2j_re2j",
        "@google_bazel_common//third_party/java/auto:value",
        "@google_bazel_common//third_party/java/error_prone:annotations",
        "@google_bazel_common//third_party/java/jsr305_annotations",
        "@google_bazel_common//third_party/java/junit",
        "@google_bazel_common//third_party/java/mockito",
        "@google_bazel_common//third_party/java/truth",
    ],
)

java_library(
    name = "compiler_tests_resources",
    resources = glob([
        "test/com/google/javascript/refactoring/examples/testdata/**/*.js",
        "src/com/google/javascript/refactoring/examples/refasterjs/**/*.js",
    ]),
)

# This is the bazel target that compiles and optimizes the J2CL app.
#
# It provides couple of convenient targets:
#  :compiler produces the compiler.js that could be used for production.
#  :compiler_dev produces the compiler_dev.js that could be used for development.
#  :compiler_dev_server serves compiler_dev.js with couple of extras which you can
#    use as a simple development server.
#
# If you like to just save a file and see the results, you can replace bazel w/ ibazel:
#   $ ibazel run :compiler_dev_server
#
j2cl_application(
    name = "compiler-j2cl",
    entry_points = ["com.google.javascript.jscomp.gwt.client.JsRunnerMain"],
    jre_checks_check_level = "MINIMAL",
    deps = [":compiler_lib-j2cl"],
)

j2cl_library(
    name = "compiler_lib-j2cl",
    srcs = [
        ":node_globals_externs",
        ":resources.js",
    ] + glob(
        [
            "src/com/google/debugging/**/*.java",
            "src/com/google/debugging/**/*.js",
            "src/com/google/javascript/rhino/**/*.java",
            "src/com/google/javascript/jscomp/*.java",
            "src/com/google/javascript/jscomp/colors/**/*.java",
            "src/com/google/javascript/jscomp/deps/**/*.java",
            "src/com/google/javascript/jscomp/lint/**/*.java",
            "src/com/google/javascript/jscomp/ijs/**/*.java",
            "src/com/google/javascript/jscomp/diagnostic/**/*.java",
            "src/com/google/javascript/jscomp/disambiguate/**/*.java",
            "src/com/google/javascript/jscomp/regex/**/*.java",
            "src/com/google/javascript/jscomp/parsing/**/*.java",
            "src/com/google/javascript/jscomp/modules/**/*.java",
            "src/com/google/javascript/jscomp/type/**/*.java",
            "src/com/google/javascript/jscomp/graph/**/*.java",
            "src/com/google/javascript/jscomp/resources/GwtProperties.*",
            "src/com/google/javascript/jscomp/resources/super-j2cl/**/*.java",
            "src/com/google/javascript/jscomp/gwt/client/JsRunnerMain.*",
            "src/com/google/javascript/jscomp/gwt/client/JsfileParserMain.*",
            "src/com/google/javascript/jscomp/gwt/client/NodePrintStream.*",
            "src/com/google/javascript/jscomp/gwt/super/**/*.java",
            "src/com/google/javascript/jscomp/gwt/super/**/*.js",
        ],
        exclude = [
            "**/super-gwt/**",
            "**/testing/**",
            "src/com/google/javascript/jscomp/deps/PathUtil.java",
        ] + ["src/" + s.split("/super/")[1] for s in glob(["**/super/**"])],
    ),
    js_suppress = ["deprecated"],
    deps = [
        ":auto_value-j2cl",
        "@com_google_code_findbugs_jsr305-j2cl",
        "@com_google_elemental2//:elemental2-core-j2cl",
        "@com_google_errorprone_error_prone_annotations-j2cl",
        "@com_google_guava-j2cl",
        "@com_google_j2cl//:jsinterop-annotations-j2cl",
        "@com_google_jsinterop_base//:jsinterop-base-j2cl",
        "@com_google_re2j-j2cl",
    ],
)

j2cl_import(
    name = "auto_value-j2cl",
    jar = "@com_google_auto_value//jar",
)

genrule(
    name = "resources_gen_js",
    srcs = ["src/com/google/javascript/jscomp/resources/resources.json"],
    outs = ["resources.js"],
    # Wrap resources.json into a goog.module that the data can be depended on
    # via goog.require in the J2CL build.
    cmd = """echo 'goog.module(\"com.google.javascript.jscomp.Resources\");
    let resources = ' > $@ &&
    cat $(SRCS) >> $@ &&
    echo ";exports = {resources: function() {return resources}};" >> $@
    """,
)

filegroup(
    name = "node_globals_externs",
    srcs = [
        "contrib/nodejs/events.js",
        "contrib/nodejs/fs.js",
        "contrib/nodejs/globals.js",
        "contrib/nodejs/stream.js",
    ],
)
